package com.boesch.electroOffice.presentation.measurement;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.model.SelectItem;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.boesch.electroOffice.business.businessObject.MeasurementBusinessObject;
import com.boesch.electroOffice.business.common.BusinessException;
import com.boesch.electroOffice.dataaccess.common.IllegalDataAccessException;
import com.boesch.electroOffice.model.electroOffice.Measurement;
import com.boesch.electroOffice.model.electroOffice.MeasurementEntry;
import com.boesch.electroOffice.model.enums.SessionParameter;
import com.boesch.electroOffice.model.enums.SubfunctionIdentifier;
import com.boesch.electroOffice.presentation.appointment.AppointmentNavigationController;
import com.boesch.electroOffice.utils.MessageUtils;
import com.boesch.electroOffice.utils.PortletUtils;
import com.boesch.electroOffice.utils.UserUtils;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.model.User;

@Controller
@ManagedBean
@SessionScoped
public class MeasurementFormController implements Serializable {

	private static final long serialVersionUID = 1648013810368109778L;
	private static final Log log = LogFactoryUtil.getLog(MeasurementFormController.class);

	@Autowired
	private MeasurementBusinessObject measurementBusinessObject;
	@Autowired
	private AppointmentNavigationController navigationController;

	private List<SelectItem> selectItemUsers = new ArrayList<SelectItem>();
	private List<MeasurementEntry> measurementEntries = new ArrayList<MeasurementEntry>();

	private Measurement measurement = new Measurement();

	private Long selectedUserId = -1L;

	private boolean measurementEntriesInitialized;
	private boolean userSelectItemsInitialized;

	public void loadData(ComponentSystemEvent event) {
		String measurementId = PortletUtils.getRequestParameter("measurementId");
		try {
			if (StringUtils.isNumeric(measurementId)) {
				measurement = measurementBusinessObject.readMeasurementById(Integer.parseInt(measurementId));
				selectedUserId = measurement.getLrUserId();
			}

			initializeSelectItemUsers();
			initializeMeasurementEntries();

		} catch (IllegalDataAccessException e) {
			log.error("Failed to load appointment from database: " + measurementId, e);
		} catch (BusinessException e) {
			log.error("Failed to load appointment from database: " + measurementId, e);
		}
	}

	public void saveMeasurement(ActionEvent event) {
		List<MeasurementEntry> mEntries = retrieveMeasurementEntries();
		measurement.setMeasurementEntries(mEntries);
		User currentUser = UserUtils.getCurrentUser();
		try {
			String returnValue = "";
			if (0 != measurement.getId()) {
				returnValue = measurementBusinessObject.updateMeasurement(measurement, currentUser);
			} else {
				returnValue = measurementBusinessObject.saveMeasurement(measurement, currentUser);
			}
			MessageUtils.addInfoMessage(returnValue);
		} catch (BusinessException e) {
			log.error("Fehler beim speichern des Messprotokolls. Bitte versuchen Sie es erneut oder wenden Sie sich an den Systemadministrator.");
		} catch (IllegalDataAccessException e) {
			log.error("Fehler beim speichern des Messprotokolls. Bitte versuchen Sie es erneut oder wenden Sie sich an den Systemadministrator.");
		}
	}

	public void cancel(ActionEvent actionEvent) {
		PortletUtils.setSessionAttribute(SessionParameter.SUBFUNCTION_KEY.getValue(), SubfunctionIdentifier.MY_APPOINTMENTS.getValue());
		navigationController.setNavigationPath("jsf/appointment/appointment_list.xhtml");
	}

	public Measurement getMeasurement() {
		return measurement;
	}

	public List<MeasurementEntry> getMeasurementEntries() {
		return measurementEntries;
	}

	public List<SelectItem> getUserList() {
		return selectItemUsers;
	}

	public long getSelectedUserId() {
		return selectedUserId;
	}

	public void setSelectedUserId(long selectedUserId) {
		this.selectedUserId = selectedUserId;
	}

	private void initializeSelectItemUsers() {
		if (!userSelectItemsInitialized) {
			try {
				List<User> users = UserUtils.getAllUsers();
				for (User user : users) {
					String userId = String.valueOf(user.getUserId());
					String fullName = user.getFullName();
					String comment = user.getComments();
					SelectItem item = new SelectItem(userId, fullName, comment);
					selectItemUsers.add(item);
				}
				userSelectItemsInitialized = true;
			} catch (SystemException e) {
				log.error("Failed to load users from liferay database.", e);
			}
		}
	}

	private void initializeMeasurementEntries() {
		if (!measurementEntriesInitialized) {
			if (null != measurement && null != measurement.getMeasurementEntries()) {
				for (MeasurementEntry entry : measurement.getMeasurementEntries()) {
					measurementEntries.add(entry);
				}
			}

			for (int i = measurementEntries.size(); i < 20; i++) {
				MeasurementEntry measurementEntry = new MeasurementEntry();
				measurementEntries.add(measurementEntry);
			}
			measurementEntriesInitialized = true;
		}
	}

	private List<MeasurementEntry> retrieveMeasurementEntries() {
		List<MeasurementEntry> entries = new ArrayList<MeasurementEntry>();
		for (MeasurementEntry entry : measurementEntries) {
			if (isFilledOutEntry(entry)) {
				entries.add(entry);
			}
		}
		return entries;
	}

	private boolean isFilledOutEntry(MeasurementEntry entry) {
		boolean returnValue = false;
		if (null != entry.getCurrentCircuitNumber() || null != entry.getDescription() || null != entry.getConductorCrossSection() || null != entry.getCharacteristic()
				|| null != entry.getRatedCurrent() || null != entry.getPeConductibility() || null != entry.getShortCircuitCurrent()
				|| null != entry.getInsulatingResistance() || null != entry.getFiRatedCurrent() || null != entry.getFiReleaseCurrent()
				|| null != entry.getFiTimeInMillis()) {
			returnValue = true;
		}
		return returnValue;
	}
}
